import { Injectable, Inject, Logger } from '@nestjs/common';
import type {
  LoggingInterface,
  StructuredLoggingInterface,
  StructuredLogData,
  RequestLogData,
  ResponseLogData,
  DatabaseQueryLogData,
  CacheOperationLogData,
  ExternalApiCallLogData,
  BusinessEventLogData,
  UserLogData,
  ErrorLogData,
  LoggingOptions,
} from './logging.interface';
import { LogLevel } from './logging.interface';

/**
 * 日志服务
 * 基于 NestJS 官方示例实现
 * 参考: https://docs.nestjs.cn/fundamentals/dependency-injection
 * 对应 Java: 日志服务
 */
@Injectable()
export class LoggingService
  implements LoggingInterface, StructuredLoggingInterface
{
  private readonly logger = new Logger(LoggingService.name);
  private currentLevel: LogLevel = LogLevel.INFO;

  constructor(
    @Inject('LOGGING_PROVIDER')
    private readonly loggingProvider: LoggingInterface,
    @Inject('STRUCTURED_LOGGING_PROVIDER')
    private readonly structuredLoggingProvider: StructuredLoggingInterface,
  ) {}

  // ==================== 基础日志接口 ====================

  /**
   * 记录调试日志
   */
  debug(message: string, context?: string, meta?: Record<string, any>): void {
    try {
      this.loggingProvider.debug(message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log debug message: ${message}`, error);
    }
  }

  /**
   * 记录信息日志
   */
  info(message: string, context?: string, meta?: Record<string, any>): void {
    try {
      this.loggingProvider.info(message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log info message: ${message}`, error);
    }
  }

  /**
   * 记录警告日志
   */
  warn(message: string, context?: string, meta?: Record<string, any>): void {
    try {
      this.loggingProvider.warn(message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log warn message: ${message}`, error);
    }
  }

  /**
   * 记录错误日志
   */
  error(message: string, context?: string, meta?: Record<string, any>): void {
    try {
      this.loggingProvider.error(message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log error message: ${message}`, error);
    }
  }

  /**
   * 记录致命错误日志
   */
  fatal(message: string, context?: string, meta?: Record<string, any>): void {
    try {
      this.loggingProvider.fatal(message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log fatal message: ${message}`, error);
    }
  }

  /**
   * 记录日志
   */
  log(
    level: LogLevel,
    message: string,
    context?: string,
    meta?: Record<string, any>,
  ): void {
    try {
      this.loggingProvider.log(level, message, context, meta);
    } catch (error) {
      this.logger.error(`Failed to log message: ${message}`, error);
    }
  }

  /**
   * 设置日志级别
   */
  setLevel(level: LogLevel): void {
    try {
      this.currentLevel = level;
      this.loggingProvider.setLevel(level);
    } catch (error) {
      this.logger.error(`Failed to set log level: ${level}`, error);
    }
  }

  /**
   * 获取当前日志级别
   */
  getLevel(): LogLevel {
    return this.currentLevel;
  }

  /**
   * 创建子日志器
   */
  child(context: string): LoggingInterface {
    try {
      return this.loggingProvider.child(context);
    } catch (error) {
      this.logger.error(`Failed to create child logger: ${context}`, error);
      return this;
    }
  }

  // ==================== 结构化日志接口 ====================

  /**
   * 记录结构化日志
   */
  logStructured(
    level: LogLevel,
    message: string,
    structuredData: StructuredLogData,
  ): void {
    try {
      this.structuredLoggingProvider.logStructured(
        level,
        message,
        structuredData,
      );
    } catch (error) {
      this.logger.error(`Failed to log structured message: ${message}`, error);
    }
  }

  /**
   * 记录请求日志
   */
  logRequest(
    request: RequestLogData,
    response: ResponseLogData,
    duration: number,
  ): void {
    try {
      this.structuredLoggingProvider.logRequest(request, response, duration);
    } catch (error) {
      this.logger.error('Failed to log request', error);
    }
  }

  /**
   * 记录数据库查询日志
   */
  logDatabaseQuery(
    query: DatabaseQueryLogData,
    duration: number,
    result?: any,
  ): void {
    try {
      this.structuredLoggingProvider.logDatabaseQuery(query, duration, result);
    } catch (error) {
      this.logger.error('Failed to log database query', error);
    }
  }

  /**
   * 记录缓存操作日志
   */
  logCacheOperation(
    operation: CacheOperationLogData,
    hit: boolean,
    duration: number,
  ): void {
    try {
      this.structuredLoggingProvider.logCacheOperation(
        operation,
        hit,
        duration,
      );
    } catch (error) {
      this.logger.error('Failed to log cache operation', error);
    }
  }

  /**
   * 记录外部API调用日志
   */
  logExternalApiCall(
    apiCall: ExternalApiCallLogData,
    response: any,
    duration: number,
  ): void {
    try {
      this.structuredLoggingProvider.logExternalApiCall(
        apiCall,
        response,
        duration,
      );
    } catch (error) {
      this.logger.error('Failed to log external API call', error);
    }
  }

  /**
   * 记录业务事件日志
   */
  logBusinessEvent(
    event: BusinessEventLogData,
    user?: UserLogData,
    meta?: Record<string, any>,
  ): void {
    try {
      this.structuredLoggingProvider.logBusinessEvent(event, user, meta);
    } catch (error) {
      this.logger.error('Failed to log business event', error);
    }
  }

  // ==================== 装饰器支持 ====================

  /**
   * 日志装饰器实现
   */
  async logMethod<T>(
    options: LoggingOptions,
    fn: () => T | Promise<T>,
    args: any[] = [],
  ): Promise<T> {
    const {
      level = LogLevel.INFO,
      context = 'Method',
      logArgs = false,
      logResult = false,
      logDuration = true,
      logError = true,
      enabled = true,
      message,
      meta = {},
    } = options;

    if (!enabled) {
      return await fn();
    }

    const startTime = Date.now();
    const logMessage = message || `${context} execution`;
    const logMeta = { ...meta };

    try {
      // 记录方法开始
      if (logArgs) {
        logMeta.args = args;
      }

      this.log(level, `${logMessage} started`, context, logMeta);

      // 执行方法
      const result = await fn();

      // 记录方法完成
      const duration = Date.now() - startTime;
      const successMeta = { ...logMeta };

      if (logResult) {
        successMeta.result = result;
      }

      if (logDuration) {
        successMeta.duration = duration;
      }

      this.log(level, `${logMessage} completed`, context, successMeta);

      return result;
    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMeta = { ...logMeta };

      if (logDuration) {
        errorMeta.duration = duration;
      }

      if (logError) {
        errorMeta.error = this.serializeError(error);
      }

      this.error(`${logMessage} failed`, context, errorMeta);
      throw error;
    }
  }

  // ==================== 工具方法 ====================

  /**
   * 序列化错误
   */
  private serializeError(error: any): ErrorLogData {
    if (error instanceof Error) {
      return {
        name: error.name,
        message: error.message,
        stack: error.stack,
        code: (error as any).code,
        cause: (error as any).cause,
        context: (error as any).context,
      };
    }

    return {
      name: 'UnknownError',
      message: String(error),
      context: { originalError: error },
    };
  }

  /**
   * 记录HTTP请求
   */
  logHttpRequest(
    method: string,
    url: string,
    statusCode: number,
    duration: number,
    userAgent?: string,
    ip?: string,
    userId?: string,
  ): void {
    const request: RequestLogData = {
      method,
      url,
      headers: {},
      ip,
      userAgent,
      userId,
    };

    const response: ResponseLogData = {
      statusCode,
      headers: {},
    };

    this.logRequest(request, response, duration);
  }

  /**
   * 记录数据库操作
   */
  logDatabaseOperation(
    operation: string,
    table: string,
    query: string,
    duration: number,
    params?: any[],
    result?: any,
  ): void {
    const queryData: DatabaseQueryLogData = {
      operation,
      table,
      query,
      params,
    };

    this.logDatabaseQuery(queryData, duration, result);
  }

  /**
   * 记录缓存操作
   */
  logCacheOperationSimple(
    operation: string,
    key: string,
    hit: boolean,
    duration: number,
    ttl?: number,
    size?: number,
  ): void {
    const operationData: CacheOperationLogData = {
      operation,
      key,
      ttl,
      size,
    };

    this.logCacheOperation(operationData, hit, duration);
  }

  /**
   * 记录外部API调用
   */
  logExternalApiCallSimple(
    service: string,
    endpoint: string,
    method: string,
    statusCode: number,
    duration: number,
    headers?: Record<string, string>,
    body?: any,
  ): void {
    const apiCall: ExternalApiCallLogData = {
      service,
      endpoint,
      method,
      headers: headers || {},
      body,
    };

    const response = { statusCode };
    this.logExternalApiCall(apiCall, response, duration);
  }

  /**
   * 记录业务事件
   */
  logBusinessEventSimple(
    event: string,
    action: string,
    resource: string,
    resourceId?: string,
    result?: 'success' | 'failure' | 'partial',
    data?: Record<string, any>,
    userId?: string,
  ): void {
    const eventData: BusinessEventLogData = {
      event,
      action,
      resource,
      resourceId,
      result,
      data,
    };

    const userData: UserLogData | undefined = userId
      ? { id: userId }
      : undefined;
    this.logBusinessEvent(eventData, userData);
  }

  /**
   * 记录性能指标
   */
  logPerformance(
    operation: string,
    duration: number,
    context?: string,
    meta?: Record<string, any>,
  ): void {
    const performanceMeta = {
      operation,
      duration,
      ...meta,
    };

    if (duration > 1000) {
      this.warn(`Slow operation: ${operation}`, context, performanceMeta);
    } else if (duration > 500) {
      this.info(`Operation: ${operation}`, context, performanceMeta);
    } else {
      this.debug(`Operation: ${operation}`, context, performanceMeta);
    }
  }

  /**
   * 记录安全事件
   */
  logSecurityEvent(
    event: string,
    severity: 'low' | 'medium' | 'high' | 'critical',
    context?: string,
    meta?: Record<string, any>,
  ): void {
    const securityMeta = {
      event,
      severity,
      ...meta,
    };

    switch (severity) {
      case 'critical':
        this.fatal(`Security event: ${event}`, context, securityMeta);
        break;
      case 'high':
        this.error(`Security event: ${event}`, context, securityMeta);
        break;
      case 'medium':
        this.warn(`Security event: ${event}`, context, securityMeta);
        break;
      case 'low':
        this.info(`Security event: ${event}`, context, securityMeta);
        break;
    }
  }

  /**
   * 记录审计日志
   */
  logAudit(
    action: string,
    resource: string,
    resourceId?: string,
    userId?: string,
    result?: 'success' | 'failure',
    meta?: Record<string, any>,
  ): void {
    const auditMeta = {
      action,
      resource,
      resourceId,
      userId,
      result,
      ...meta,
    };

    this.info(`Audit: ${action} on ${resource}`, 'audit', auditMeta);
  }
}
